package com.gmail.jaredjeya.awesomeplatformer.view;

import java.util.HashMap;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;

import com.gmail.jaredjeya.awesomeplatformer.Constants;
import com.gmail.jaredjeya.awesomeplatformer.model.Game;
import com.gmail.jaredjeya.awesomeplatformer.model.InputHandler;
import com.gmail.jaredjeya.awesomeplatformer.model.UpdateThread;
import com.gmail.jaredjeya.awesomeplatformer.model.level.Level;
import com.gmail.jaredjeya.awesomeplatformer.model.sprites.Sprite;

public class Display {

	protected Game					game;

	/**
	 * The absolute size of the screen.
	 */
	private int						sizeX, sizeY;

	/**
	 * The absolute offset used to centre the image.
	 */
	private int						offsetX, offsetY;

	/**
	 * The locations of each button.
	 */
	private int						buttonT, leftL, rightL, shootL, jumpL;

	/**
	 * The final height and width of the rendered image.
	 */
	private int						finalWidth, finalHeight;

	/**
	 * A cache holding scaled images - increases FPS dramatically.
	 */
	private HashMap<String, Bitmap>	spriteCache;

	private float					scaleSize;

	private Level					currentLevel;

	private InputHandler			inputHandler;

	public Display(Game game) {
		this.game = game;
		inputHandler = game.getInputHandler();
		currentLevel = null;
		spriteCache = new HashMap<String, Bitmap>();
	}

	public void setup(Canvas canvas, Paint paint) {
		// paint.setXfermode(new PorterDuffXfermode (PorterDuff.));
		sizeX = canvas.getWidth();
		sizeY = canvas.getHeight();
		inputHandler.setSize(sizeX, sizeY);
		buttonT = sizeY - (Constants.BUTTON_SIZE + Constants.BUTTON_SEPARATION);
		leftL = Constants.BUTTON_SEPARATION;
		rightL = 2 * Constants.BUTTON_SEPARATION + Constants.BUTTON_SIZE;
		shootL = sizeX - (2 * Constants.BUTTON_SEPARATION + 2 * Constants.BUTTON_SIZE);
		jumpL = sizeX - (Constants.BUTTON_SEPARATION + Constants.BUTTON_SIZE);
		spriteCache.put("left", Sprite.leftButtonSprite.getBitmap(Constants.BUTTON_SIZE, Constants.BUTTON_SIZE));
		spriteCache.put("right", Sprite.rightButtonSprite.getBitmap(Constants.BUTTON_SIZE, Constants.BUTTON_SIZE));
		spriteCache.put("shoot", Sprite.shootButtonSprite.getBitmap(Constants.BUTTON_SIZE, Constants.BUTTON_SIZE));
		spriteCache.put("jump", Sprite.jumpButtonSprite.getBitmap(Constants.BUTTON_SIZE, Constants.BUTTON_SIZE));
		spriteCache.put("leftP", Sprite.leftButtonSpriteP.getBitmap(Constants.BUTTON_SIZE, Constants.BUTTON_SIZE));
		spriteCache.put("rightP", Sprite.rightButtonSpriteP.getBitmap(Constants.BUTTON_SIZE, Constants.BUTTON_SIZE));
		spriteCache.put("shootP", Sprite.shootButtonSpriteP.getBitmap(Constants.BUTTON_SIZE, Constants.BUTTON_SIZE));
		spriteCache.put("jumpP", Sprite.jumpButtonSpriteP.getBitmap(Constants.BUTTON_SIZE, Constants.BUTTON_SIZE));

	}

	public void draw(Canvas canvas, Paint paint) {
		sizeX = canvas.getWidth();
		sizeY = canvas.getHeight();
		canvas.drawARGB(255, 0, 0, 0);

		Level level = game.getCurrentLevel();
		if (level != currentLevel) {
			Log.v(Constants.DEBUG_TAG, "yolo");
			currentLevel = level;
			scaleSize = Math.min((float) (sizeY / level.height), (float) (sizeX / level.width)) / (float) Constants.GRID_SIZE;
			finalWidth = (int) (scaleSize * Constants.GRID_SIZE * level.width);
			finalHeight = (int) (scaleSize * Constants.GRID_SIZE * level.height);

			if (finalWidth == sizeX) offsetY = (sizeY - finalHeight) / 2;
			else offsetX = (sizeX - finalWidth) / 2;

			reloadCache();
		}

		renderTiles(canvas, paint, level);
		renderPlayer(canvas, paint);
		if (!inputHandler.dPad && !inputHandler.hardwareKeyboard && !inputHandler.numericKeyboard) renderButtons(canvas, paint);

		paint.setARGB(255, 0, 255, 0);
		canvas.drawText("FPS: " + RenderThread.fpsDraw + " UPS: " + UpdateThread.upsDraw, 20, 20, paint);
	}

	private void renderTiles(Canvas canvas, Paint paint, Level level) {

		for (int x = 0; x < level.width; x++) {
			for (int y = 0; y < level.height; y++) {

				Bitmap bmp = spriteCache.get(level.getTileAt(x, y).getSprite().name);

				float posX = x * scaleSize * Constants.GRID_SIZE + offsetX;
				float posY = y * scaleSize * Constants.GRID_SIZE + offsetY;

				canvas.drawBitmap(bmp, posX, posY, paint);

			}
		}
	}

	private void renderButtons(Canvas canvas, Paint paint) {
		if (inputHandler.leftPressed) canvas.drawBitmap(spriteCache.get("leftP"), leftL, buttonT, paint);
		else canvas.drawBitmap(spriteCache.get("left"), leftL, buttonT, paint);

		if (inputHandler.rightPressed) canvas.drawBitmap(spriteCache.get("rightP"), rightL, buttonT, paint);
		else canvas.drawBitmap(spriteCache.get("right"), rightL, buttonT, paint);

		if (inputHandler.shootPressed) canvas.drawBitmap(spriteCache.get("shootP"), shootL, buttonT, paint);
		else canvas.drawBitmap(spriteCache.get("shoot"), shootL, buttonT, paint);

		if (inputHandler.jumpPressed) canvas.drawBitmap(spriteCache.get("jumpP"), jumpL, buttonT, paint);
		else canvas.drawBitmap(spriteCache.get("jump"), jumpL, buttonT, paint);
	}

	private void renderPlayer(Canvas canvas, Paint paint) {
		Bitmap bmp = spriteCache.get(game.player.getSprite().name);
		float xPos = game.player.xPos * scaleSize * Constants.GRID_SIZE + offsetX - (Constants.PLAYER_SIZE * scaleSize / 2F);
		float yPos = game.player.yPos * scaleSize * Constants.GRID_SIZE + offsetY - (Constants.PLAYER_SIZE * scaleSize / 2F);
		canvas.drawBitmap(bmp, xPos, yPos, paint);
	}

	private void reloadCache() {
		spriteCache.put("blue", Sprite.blueSprite.getBitmap((int) (scaleSize * Constants.TILE_SIZE), (int) (scaleSize * Constants.TILE_SIZE)));
		spriteCache.put("red", Sprite.redSprite.getBitmap((int) (scaleSize * Constants.TILE_SIZE), (int) (scaleSize * Constants.TILE_SIZE)));
		spriteCache.put("bg", Sprite.blackSprite.getBitmap((int) (scaleSize * Constants.TILE_SIZE), (int) (scaleSize * Constants.TILE_SIZE)));
		spriteCache.put("green", Sprite.greenSprite.getBitmap((int) (scaleSize * Constants.TILE_SIZE), (int) (scaleSize * Constants.TILE_SIZE)));
		spriteCache.put("player", Sprite.playerSprite.getBitmap((int) (scaleSize * Constants.PLAYER_SIZE), (int) (scaleSize * Constants.PLAYER_SIZE)));
	}

}
